﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sustainalytics.Entities;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;

namespace Sustainalytics.ScreeningTool.Service.Tests
{
    [TestClass()]
    public class CriteriaLevel2ControllerTests
    {
        [TestMethod]
        public void Get()
        {
            Guid companyInfoCriteriaLevel1Id = Guid.NewGuid();
            Guid esgCompositeCriteriaLevel1Id = Guid.NewGuid();
            Guid businessOverviewCriteriaLevel2Id = Guid.NewGuid();
            Guid generalCriteriaLevel2Id = Guid.NewGuid();
            Guid esgEventsCriteriaLevel2Id = Guid.NewGuid();
            List<CriteriaLevel2> criteriaLevel2List = new List<CriteriaLevel2>();
            criteriaLevel2List.Add(new CriteriaLevel2() { Id = businessOverviewCriteriaLevel2Id, CriteriaLevel1Id = companyInfoCriteriaLevel1Id, Name = "Business overview" });
            criteriaLevel2List.Add(new CriteriaLevel2() { Id = generalCriteriaLevel2Id, CriteriaLevel1Id = companyInfoCriteriaLevel1Id, Name = "General" });
            criteriaLevel2List.Add(new CriteriaLevel2() { Id = esgEventsCriteriaLevel2Id, CriteriaLevel1Id = esgCompositeCriteriaLevel1Id, Name = "Event Indicators" });
            criteriaLevel2List.Add(new CriteriaLevel2() { Id = Guid.NewGuid(), CriteriaLevel1Id = esgCompositeCriteriaLevel1Id, Name = "EmptyTabLevel2" });
            List<BaseCriteria> baseCriteriaList = new List<BaseCriteria>();
            baseCriteriaList.Add(new BaseCriteria() { Id = Guid.NewGuid(), Name = "Market capitalization", CriteriaEntity = "FinancialData", CriteriaEntityField = "MarketCapitalization", CriteriaLevel2Id = businessOverviewCriteriaLevel2Id, CriteriaType = CriteriaTypeEnum.CriteriaType1 });
            baseCriteriaList.Add(new BaseCriteria() { Id = Guid.NewGuid(), Name = "Number of employees", CriteriaEntity = "CompanyInfo", CriteriaEntityField = "NumberOfEmployees", CriteriaLevel2Id = generalCriteriaLevel2Id, CriteriaType = CriteriaTypeEnum.CriteriaType1 });
            baseCriteriaList.Add(new BaseCriteria() { Id = Guid.NewGuid(), Name = "Basic labour standards", CriteriaEntity = "EventIndicator", CriteriaEntityField = "BaseEventIndicatorId", CriteriaLevel2Id = esgEventsCriteriaLevel2Id, CriteriaType = CriteriaTypeEnum.CriteriaType2 });
            baseCriteriaList.Add(new BaseCriteria() { Id = Guid.NewGuid(), Name = "Business Ethics", CriteriaEntity = "EventIndicator", CriteriaEntityField = "BaseEventIndicatorId", CriteriaLevel2Id = esgEventsCriteriaLevel2Id, CriteriaType = CriteriaTypeEnum.CriteriaType2 });
            baseCriteriaList.Add(new BaseCriteria() { Id = Guid.NewGuid(), Name = "Child Labour", CriteriaEntity = "EventIndicator", CriteriaEntityField = "BaseEventIndicatorId", CriteriaLevel2Id = esgEventsCriteriaLevel2Id, CriteriaType = CriteriaTypeEnum.CriteriaType2 });


            var companyScreeningService = new Sustainalytics.ScreeningTool.BL.Fakes.StubICompanyScreening()
            {
                GetCriteriaLevelTwoGuid = (id) =>
                {
                    return criteriaLevel2List.Where(cr2 => cr2.Id == id).SingleOrDefault();
                },
                ListCriteriaLevelTwoNullableOfGuid = (criteriaLevel1Id) =>
                {
                    if (criteriaLevel1Id.HasValue)
                        return criteriaLevel2List.Where(cr2=> cr2.CriteriaLevel1Id == criteriaLevel1Id).ToList();

                    return criteriaLevel2List;
                },
                ListBaseCriteriaNullableOfGuid = (criteriaLevel2Id) =>
                {
                    if (criteriaLevel2Id.HasValue)
                        return baseCriteriaList.Where(bc => bc.CriteriaLevel2Id == criteriaLevel2Id).ToList();

                    return baseCriteriaList;
                }
            };

            var criteriaLevel2Controller = Utils.setupController<CriteriaLevel2Controller>(new CriteriaLevel2Controller(companyScreeningService, null));

            ListOptions options = new ListOptions();
            List<CriteriaLevel2Dto> criteriaLevel2DtoList = new List<CriteriaLevel2Dto>();
            HttpResponseMessage criteriaTabs = criteriaLevel2Controller.Get(companyInfoCriteriaLevel1Id, options, true);

            Assert.IsNotNull(criteriaTabs, "The criteria tabs should not be null.");
            Assert.IsTrue(criteriaTabs.IsSuccessStatusCode, "The request has failed.");
            Assert.IsTrue(criteriaTabs.TryGetContentValue<List<CriteriaLevel2Dto>>(out criteriaLevel2DtoList), "The response does not contain the list of criteria level 2 dto.");
            Assert.AreEqual(criteriaLevel2List.Count(i => i.CriteriaLevel1Id == companyInfoCriteriaLevel1Id), criteriaLevel2DtoList.Count, "The number of criteria level 2 is different than the expected one.");

            List<object> objectList = new List<object>();
            criteriaTabs = criteriaLevel2Controller.Get(companyInfoCriteriaLevel1Id, options);

            Assert.IsNotNull(criteriaTabs, "The criteria tabs should not be null.");
            Assert.IsTrue(criteriaTabs.IsSuccessStatusCode, "The request has failed.");
            Assert.IsTrue(criteriaTabs.TryGetContentValue<List<object>>(out objectList), "The response does not contain the list of criteria level 1 dto.");
            Assert.AreEqual(criteriaLevel2List.Count(i => i.CriteriaLevel1Id == companyInfoCriteriaLevel1Id), objectList.Count, "The number of criteria level 1 is different than the expected ones");

            criteriaTabs = criteriaLevel2Controller.Get(businessOverviewCriteriaLevel2Id);
            object criteriaLevel2 = null;
            Assert.IsNotNull(criteriaTabs, "The criteria level 2 dto should not be null.");
            Assert.IsTrue(criteriaTabs.IsSuccessStatusCode, "The request has failed.");
            Assert.IsTrue(criteriaTabs.TryGetContentValue<object>(out criteriaLevel2), "The response does not contain the criteria level 2 dto.");

            criteriaTabs = criteriaLevel2Controller.Get(businessOverviewCriteriaLevel2Id, true);
            CriteriaLevel2Dto criteriaLevel2Dto = null;
            Assert.IsNotNull(criteriaTabs, "The criteria level 2 dto should not be null.");
            Assert.IsTrue(criteriaTabs.IsSuccessStatusCode, "The request has failed.");
            Assert.IsTrue(criteriaTabs.TryGetContentValue<CriteriaLevel2Dto>(out criteriaLevel2Dto), "The response does not contain the criteria level 2 dto.");
            Assert.AreEqual(baseCriteriaList.Count(c => c.CriteriaLevel2Id == businessOverviewCriteriaLevel2Id), criteriaLevel2Dto.BaseCriteria.Count, "The number of base criteria is different than the expected one.");
            Assert.AreEqual(businessOverviewCriteriaLevel2Id, criteriaLevel2Dto.Id, "The id of the criteria level 2 is different than the excpected one.");
        }
    }
}
